package com.bc.bcpayservice;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.management.ManagementFactory;
import java.util.*;

import com.bc.bcapi.dao.T_Inner_transMapper;
import com.bc.bcapi.dao.T_TxhashMapper;
import com.bc.bcapi.dao.T_User_walletMapper;
import com.bc.bcapi.dao.T_User_withdrawMapper;
import com.bc.bcapi.service.*;
import com.bc.bcapi.utils.web3j.ERC20TransactionModel;
import com.bc.bcapi.utils.web3j.TransModel;
import com.bc.bcmodel.domain.T_Inner_transModel;
import com.bc.bcmodel.domain.T_TxhashModel;
import com.bc.bcmodel.domain.T_User_walletModel;
import com.bc.bcmodel.domain.T_User_withdrawModel;
import com.bc.commoncore.util.SpringBeanHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.web3j.protocol.core.methods.response.Transaction;

public class Main {

//    @Autowired
//    T_Account_logService t_account_logService;

    private final static Logger log = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) throws Exception {
        ApplicationContext contentApp = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        SpringBeanHelper.setApplicationContext(contentApp);
        /* 加载定时任务 */
        writePID();// 生成PID
        Exec();
    }

    private static void writePID() throws IOException {
        File f = new File("device.pid");
        OutputStreamWriter writer = new OutputStreamWriter(
                new FileOutputStream(f));
        String processName = ManagementFactory.getRuntimeMXBean().getName();
        String pid = processName.substring(0, processName.indexOf("@"));
        writer.write(String.valueOf(pid));
        writer.flush();
        writer.close();
    }

    /**
     * do everything
     */
    public static void Exec() {
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                ///TODO do everything  执行任务
                try {
                    watcher();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        Timer timer = new Timer();
        //这里的睡眠时间还是建议睡眠个500毫秒，让CPU回收一下。
        long delay = 1000;
        long intevalPeriod = 1000;
        timer.scheduleAtFixedRate(task, delay, intevalPeriod);
    }

    private static void watcher() throws Exception {
        //因为包的scan是后加载的，所以不能使用注入的方式获取类或对象
        //使用SprintBeanHelper对象获取就好。

        BlockChainListenerService blockChainListenerService = SpringBeanHelper.getCustomBeanByType(BlockChainListenerService.class);
        RechargeService rechargeService = SpringBeanHelper.getCustomBeanByType(RechargeService.class);
        //T_Inner_transService t_inner_transService = SpringBeanHelper.getCustomBeanByType(T_Inner_transService.class);
        TransColdService transColdService = SpringBeanHelper.getCustomBeanByType(TransColdService.class);
        TransGasService transGasService = SpringBeanHelper.getCustomBeanByType(TransGasService.class);
        T_User_withdrawService t_user_withdrawService = SpringBeanHelper.getCustomBeanByType(T_User_withdrawService.class);
        T_User_withdrawMapper t_user_withdrawMapper = SpringBeanHelper.getCustomBeanByType(T_User_withdrawMapper.class);
        T_Inner_transMapper t_inner_transMapper = SpringBeanHelper.getCustomBeanByType(T_Inner_transMapper.class);
        T_TxhashMapper t_txhashMapper = SpringBeanHelper.getCustomBeanByType(T_TxhashMapper.class);
        T_User_walletMapper t_user_walletMapper = SpringBeanHelper.getCustomBeanByType(T_User_walletMapper.class);

        List<ERC20TransactionModel> transactionModels = blockChainListenerService.scanBlock();
        if (transactionModels == null) return;
        List<String> txHashs = blockChainListenerService.getTxHashs();
        Map<String, T_TxhashModel> t_txhashModelMap = new HashMap<>();
        if (txHashs.size() > 0) {
            List<T_TxhashModel> txhashModels = t_txhashMapper.findHashes(txHashs);
            for (T_TxhashModel t_txhashModel : txhashModels)
                t_txhashModelMap.put(t_txhashModel.getTxhash(), t_txhashModel);
        }

        for (ERC20TransactionModel transactionModel: transactionModels) {
            String txhash = transactionModel.getTxhash();
            boolean status = transactionModel.getStatus();
            blockChainListenerService.closeTxHash(txhash);
            if (t_txhashModelMap.containsKey(txhash)) {
                //系统里存在这笔交易
                T_TxhashModel t_txhashModel = t_txhashModelMap.get(txhash);
                //更新状态，实际花费
                T_TxhashModel updateModel = new T_TxhashModel();
                updateModel.setId(t_txhashModel.getId());
                updateModel.setGas_used(transactionModel.getGasUsed());
                updateModel.setFee(transactionModel.getGasCost());
                updateModel.setStatus(String.valueOf(status));
                t_txhashMapper.update(updateModel);

                switch (t_txhashModel.getTranstype()) {
                    case 1:
                        //withdraw
                        T_User_withdrawModel t_user_withdrawModel = t_user_withdrawMapper.getByWithdrawId(t_txhashModel.getWithdraw_id());
                        if (status) t_user_withdrawService.withdrawSuccess(t_user_withdrawModel);
                        else t_user_withdrawService.withdrawFailed(t_user_withdrawModel);
                        break;
                    case 2:
                        //cold_trans
                        T_Inner_transModel transColdModel = t_inner_transMapper.getByInnerTransId(t_txhashModel.getWithdraw_id());
                        if (status) transColdService.transColdSuccess(transColdModel);
                        else transColdService.transColdFail(transColdModel, transactionModel);
                        break;
                    case 3:
                        //gas_trans
                        T_Inner_transModel transGasModel = t_inner_transMapper.getByInnerTransId(t_txhashModel.getWithdraw_id());
                        transGasService.transGas(transGasModel, transactionModel, status);
                }
            } else {
                //查询是否充值
                if (status) {
                    for (TransModel transModel : transactionModel.getTransModels()) {
                        String to_address = transModel.getTo();
                        //查询to是否是我们的地址
                        T_User_walletModel t_user_walletModel = t_user_walletMapper.getWalletByAddress(to_address);
                        //充值
                        if (t_user_walletModel != null)
                            rechargeService.recharge(t_user_walletModel, transactionModel, transModel);
                    }
                }
            }
            //一条transaction处理完毕
        }
        //一个block处理完毕
        blockChainListenerService.closeBlock();
    }
}
